﻿using MultiAgentsClient.ChatDataStructures;
using MultiAgentsShared;
using OpenAI.ObjectModels;
using OpenAI.ObjectModels.RequestModels;
using static MultiAgentsServer.Scripts.Database.DatabaseRepository;
using System.Security.Cryptography;
using System.Text;
using MultiAgentsServer.Pages;

namespace MultiAgentsServer.Scripts.Database;

public class DataBaseOperationService(DatabaseRepository databaseRepository)
{
    private readonly DatabaseRepository databaseRepository = databaseRepository;

    #region UserRelated
    public void AddUser(string username, string password, string salt)
    {
        // TODO: Check string to prevent injection attacks.
        UserDB user = new()
        {
            Name = username,
            Password = password,
            Salt = salt
        };
        int userId = databaseRepository.AddRow(DataBaseTableNames.Users.ToString(), user);
        if (userId < 0)
        {
            throw new Exception("Add user failed.");
        }
    }

    public UserDB? GetUserByName(string userName)
    {
        UserDB userDBs = new()
        {
            Name = userName,
        };

        List<UserDB> users = databaseRepository.QueryRows(DataBaseTableNames.Users.ToString(), userDBs);
        if (users.Count == 0)
        {
            return null;
        }
        return users[0];
    }

    public UserDB? GetUserById(int userId)
    {
        UserDB userDBs = new()
        {
            Id = userId,
        };

        List<UserDB> users = databaseRepository.QueryRows(DataBaseTableNames.Users.ToString(), userDBs);
        if (users.Count == 0)
        {
            return null;
        }
        return users[0];
    }

    public bool GetIsAllowToolCallByUserId(int userId)
    {
        UserDB userDB = new()
        {
            Id = userId,
        };

        List<UserDB> users = databaseRepository.QueryRows(DataBaseTableNames.Users.ToString(), userDB);
        if (users.Count == 0)
        {
            return false;
        }
        return users[0].AllowToolCall;
    }

    public UserDataModel FetchUserdata(int userId)
    {
        UserDB userDB = new()
        {
            Id = userId,
        };

        List<UserDB> userList = databaseRepository.QueryRows(DataBaseTableNames.Users.ToString(), userDB);

        if (userList.Count == 0)
        {
            throw Debug.ShouldNotHappen();
        }

        userDB = userList[0];
        UserDataModel userData = new(userId, userDB.Name)
        {
            Id = userId,
            selectedChatRoomId = userDB.SelectedChatRoomId,
            selectedPrjId = userDB.SelectedProjectId,
            chatAccessibleLlmModels =userDB.AccessChatModels,
            workflowAccessibleLlmModels = userDB.AccessWorkflowModels,
            allowToolCall = userDB.AllowToolCall,
        };

        ProjectDB projectDB = new()
        {
            UserId = userId,
            Status = ProjectDB.ProjectStatus.Unarchived,
        };

        List<ProjectDB> projects = databaseRepository.QueryRows(DataBaseTableNames.Projects.ToString(), projectDB);
        foreach (ProjectDB project in projects)
        {
            ChatProject newChatProject = userData.CreateProject(project.Id, project.Name, project.Setting);

            ChatRoomDB chatRoomDB = new()
            {
                ProjectId = project.Id,
                Status = ChatRoomDB.ChatRoomStatus.Unarchived,
            };

            List<ChatRoomDB> chatRoomDBs = databaseRepository.QueryRows(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);

            foreach (ChatRoomDB chatRoom in chatRoomDBs)
            {
                newChatProject.CreateChatRoom(chatRoom.Id, chatRoom.AIRenamed, chatRoom.Name);
            }
        }

        return userData;
    }

    public void RefreshUserSelectedChatRoomId(int userId, int chatRoomId, int projectId)
    {
        UserDB userDB = new()
        {
            Id = userId,
            SelectedChatRoomId = chatRoomId,
            SelectedProjectId = projectId,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.Users.ToString(), userDB);
        if (!success)
        {
            throw new Exception("Refresh selected chat room Id failed.");
        }
    }

    public void RefreshUserLastLoginTime(int userId, DateTime time)
    {
        UserDB userDB = new()
        {
            Id = userId,
            LastLoginTime = time,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.Users.ToString(), userDB);

        if (!success)
        {
            throw new Exception("Refresh user last login time failed.");
        }
    }

    public void UpdateAllowToolCall(int userId, bool allow)
    {
        UserDB userDB = new()
        {
            Id = userId,
            AllowToolCall = allow,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.Users.ToString(), userDB);
    }

    public void ChangeUserPassword(int userId, string password, string salt)
    {
        UserDB userDB = new()
        {
            Id = userId,
            Password = password,
            Salt = salt,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.Users.ToString(), userDB);
    }
    #endregion

    #region ProjectSettings
    public string FetchProjectSettings(int userId, int prjId)
    {
        ProjectDB projectDB = new()
        {
            Id = prjId,
        };

        List<ProjectDB> projectDBList = databaseRepository.QueryRows(DataBaseTableNames.Projects.ToString(), projectDB);
        if (projectDBList.Count == 0)
        {
            return "";
        }

        int projectUserId = projectDBList[0].UserId;
        if (projectUserId != userId) {
            Debug.LogError($"Prj Not belong to userId {userId}");
            throw new Exception("ProjectId could not match userId.");
        }

        return projectDBList[0].Setting ?? "";
    }

    public void UpdateProjectSettings(int userId, int prjId, string prjSettings)
    {
        //TODO:Check string to prevent injection attacks.
        ProjectDB projectDB = new()
        {
            Id = prjId,
        };

        List<ProjectDB> projectDBList = databaseRepository.QueryRows(DataBaseTableNames.Projects.ToString(), projectDB);
        if (projectDBList.Count == 0)
        {
            return;
        }

        int projectUserId = projectDBList[0].UserId;
        if (projectUserId != userId)
        {
            Debug.LogError($"PrjId {prjId} Not belong to userId {userId}");
            throw new Exception("ProjectId could not match userId.");
        }

        projectDB.Setting = prjSettings;
        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.Projects.ToString(), projectDB);
        if (!success)
        {
            throw new Exception("Update project settings failed.");
        }
    }
    #endregion

    #region Agents
    public int AddAgentTemplate(int userId, AgentTemplate agentTemplate)
    {
        AgentTemplateDB agentTemplateDB = agentTemplate.ToDb();
        agentTemplateDB.UserId = userId;

        int agentTemplateId = databaseRepository.AddRow(DataBaseTableNames.AgentTemplates.ToString(), agentTemplateDB);

        return agentTemplateId;
    }

    public List<AgentTemplateDB> FetchAgentTemplates(int userId)
    {
        AgentTemplateDB agentTemplateDB = new()
        {
            UserId = userId,
        };

        List<AgentTemplateDB> agentTemplateDBs = databaseRepository.QueryRows(DataBaseTableNames.AgentTemplates.ToString(), agentTemplateDB);

        return agentTemplateDBs;
    }

    public int GetAgentInstanceIdInRoom(int chatRoomId, int agentTemplateId)
    {
        AgentInstanceDB agentInstanceDB = new()
        {
            ChatRoomId = chatRoomId,
            TypeId = agentTemplateId,
        };
        List<AgentInstanceDB> agents = databaseRepository.QueryRows(DataBaseTableNames.AgentInstances.ToString(), agentInstanceDB);
        return agents.Count > 0 ? agents[0].Id : -1;
    }
    #endregion

    #region Msgs
    // TODO: Remove?
    public int AddToolMessageToChatRoom(int chatRoomId, int userId, int agentId, string toolCallId, string toolCallResult, List<int> historyMessagesIdList)
    {
        //TODO:Check string to prevent injection attacks.
        MessageDB newMessage = new()
        {
            ChatRoomId = chatRoomId,
            UserId = userId,
            AgentId = agentId,
            Role = StaticValues.ChatMessageRoles.Tool,
            Author = "",
            Content = toolCallResult,
            HistoryMessagesIdList = historyMessagesIdList,
            ToolCallId = toolCallId,
            Time = DateTime.Now,
            ToolCalls = "",
        };

        return databaseRepository.AddRow(DataBaseTableNames.Messages + "_1", newMessage);
    }

    public MessageDB? GetMessageById(int messageId)
    {
        //TODO:Check string to prevent injection attacks.
        MessageDB newMessage = new()
        {
            Id = messageId,
        };

        List<MessageDB> messages = databaseRepository.QueryRows(DataBaseTableNames.Messages + "_1", newMessage);
        if (messages.Count == 0)
        {
            return null;
        }

        return messages[0];
    }

    //add user/assistent/system msg to chatRoom
    public int AddMessageToChatRoom(int chatRoomId, int userId, int agentId, string role, string author, string content, List<int> historyMessagesIdList, Dictionary<int, string> imageIdAndNameList, Dictionary<int, string> textFileIdAndNameList, DateTime dateTime, List<ToolCall>? toolCalls = null)
    {
        var toolCallJson = "";
        if (toolCalls != null && toolCalls.Count > 0)
        {
            toolCallJson = SerializableObjectBase.ConvertToJson(toolCalls);
        }

        //TODO:Check string to prevent injection attacks.
        MessageDB newMessage = new()
        {
            ChatRoomId = chatRoomId,
            UserId = userId,
            AgentId = agentId,
            Role = role,
            Author = author,
            Content = content,
            HistoryMessagesIdList = historyMessagesIdList,
            ImageList = imageIdAndNameList,
            TextFileList = textFileIdAndNameList,
            Time = dateTime,
            ToolCalls = toolCallJson,
        };
            
        return databaseRepository.AddRow(DataBaseTableNames.Messages + "_1", newMessage);
    }
    
    public int GetDefaultAgentIdByChatRoomID(int chatRoomId)
    {
        AgentInstanceDB agentInstanceDB = new()
        {
            ChatRoomId = chatRoomId,
        };

        List<AgentInstanceDB> agentInstanceDBs = databaseRepository.QueryRows(DataBaseTableNames.AgentInstances.ToString(), agentInstanceDB);
        if (agentInstanceDBs.Count > 0)
        {
            return agentInstanceDBs[0].Id;
        }

        return -1;
    }

    public bool UpdateMessageContent(int messageId, string newContent, string? toolCallJson, DateTime dateTime)
    {
        if (string.IsNullOrEmpty(newContent) && string.IsNullOrEmpty(toolCallJson))
        {
            Debug.LogError("msg is null and toolCall is empty");
            throw Debug.ShouldNotHappen();
        }

        MessageDB messageDB = new()
        {
            Id = messageId,
            Content = newContent,
            ToolCalls = toolCallJson ?? "",
            Time = dateTime,
        };

        return databaseRepository.UpdateRowById(DataBaseTableNames.Messages.ToString() + "_1", messageDB);
    }

    public bool UpdateMessageHistory(int messageId, List<int> historyMessagesIdList)
    {
        MessageDB messageDB = new()
        {
            Id = messageId,
            HistoryMessagesIdList = historyMessagesIdList
        };

        return databaseRepository.UpdateRowById(DataBaseTableNames.Messages.ToString() + "_1", messageDB);
    }

    public void RemoveToolCallsByAssistantMessageId(int messageId, string content, string toolCalls)
    {
        MessageDB messageDB = new()
        {
            Id = messageId,
            Content = content + toolCalls + "\nTool call failed.",
            ToolCalls = "",
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.Messages.ToString() + "_1", messageDB);

        if (success == false)
        {
            throw Debug.ShouldNotHappen();
        }
    }
    #endregion

    #region ChatPrj
    public int AddProjectForUser(int userId, string projectName, string prjSettings)
    {
        //TODO:Check string to prevent injection attacks.
        ProjectDB newProject = new()
        {
            UserId = userId,
            Name = projectName,
            Setting = prjSettings,
        };

        return databaseRepository.AddRow(DataBaseTableNames.Projects.ToString(), newProject);
    }

    public bool DeleteProject(int projectId)
    {
        //TODO:Check string to prevent injection attacks.
        ProjectDB projectDB = new()
        {
            Id = projectId,
            Status = ProjectDB.ProjectStatus.Delete,
        };

        return databaseRepository.UpdateRowById(DataBaseTableNames.Projects.ToString(), projectDB);
    }

    public int? GetProjectIdByChatRoomId(int chatRoomId)
    {
        ChatRoomDB chatRoomDB = new()
        {
           Id = chatRoomId,
        };

        List<ChatRoomDB> chatRoomDBs = databaseRepository.QueryRows(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);
        if (chatRoomDBs.Count == 0)
        {
            return null;
        }

        return chatRoomDBs[0].ProjectId;
    }
    #endregion

    #region ChatRoom
    public int AddChatRoomToProject(int userId, int projectId, string chatRoomName, bool aiRenamedIn)
    {
        //TODO:Check string to prevent injection attacks.
        ProjectDB projectDB = new()
        {
            Id = projectId,
        };

        List<ProjectDB> projectDBList = databaseRepository.QueryRows(DataBaseTableNames.Projects.ToString(), projectDB);
        if (projectDBList.Count == 0)
        {
            return -1;
        }

        int projectUserId = projectDBList[0].UserId;
        if (projectUserId != userId) {
            Debug.LogError($"Prj Not belong to userId {userId}");
            throw new Exception("ProjectId could not match userId.");
        }

        ChatRoomDB newChatRoom = new()
        {
            ProjectId = projectId,
            AIRenamed = aiRenamedIn,
            Name = chatRoomName,
        };

        return databaseRepository.AddRow(DataBaseTableNames.ChatRooms.ToString(), newChatRoom);
    }

    public ChatRoomDB? GetChatRoom(int chatRoomId)
    {
        ChatRoomDB chatRoomDB = new()
        {
            Id = chatRoomId,
        };

        List<ChatRoomDB> chatRoomDBs = databaseRepository.QueryRows(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);
        if (chatRoomDBs.Count == 0)
        {
            return null;
        }

        return chatRoomDBs[0];
    }

    public void RenameChatRoom(int chatRoomId, string chatRoomName)
    {
        ChatRoomDB chatRoomDB = new()
        {
            Id = chatRoomId,
            Name = chatRoomName,
            AIRenamed = true,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);
        if (success == false)
        {
            throw Debug.ShouldNotHappen();
        }
    }

    public int GetChatRoomLastMessageId(int chatRoomId)
    {
        ChatRoomDB chatRoomDB = new()
        {
            Id = chatRoomId,
        };

        List<ChatRoomDB> chatRoomDBs = databaseRepository.QueryRows(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);
        if (chatRoomDBs.Count == 0)
        {
            return -1;
        }

        if (chatRoomDBs[0].LastMessageId == 0)
        {
            return 0;
        }
        else
        {
            return chatRoomDBs[0].LastMessageId;
        }
    }

    public List<MessageDB> GetChatRoomMessages(int chatRoomId)
    {
        ChatRoomDB chatRoomDB = new()
        {
            Id = chatRoomId,
        };

        List<ChatRoomDB> chatRoomDBs = databaseRepository.QueryRows(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);
        if (chatRoomDBs.Count == 0)
        {
            return [];
        }

        MessageDB messageDB = new()
        {
            ChatRoomId = chatRoomId,
        };

        List<MessageDB> messageDBs = databaseRepository.QueryRows(DataBaseTableNames.Messages.ToString() + "_1", messageDB);

        return messageDBs;
    }

    public bool UpdateChatRoomLastMessage(int chatRoomId, int messageId)
    {
        if (messageId != 0)
        {
            MessageDB messageDB = new()
            {
                Id = messageId,
            };

            List<MessageDB> messageDBs = databaseRepository.QueryRows(DataBaseTableNames.Messages.ToString() + "_1", messageDB);

            if (messageDBs.Count == 0 || messageDBs.Last().ChatRoomId != chatRoomId)
            {
                return false;
            }
        }

        ChatRoomDB chatRoomDB = new()
        {
            Id = chatRoomId,
            LastMessageId = messageId
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);

        return success;
    }

    public int AddAgentToChatRoom(int chatRoomId, int typeId, string LLMModel, float temperature, List<string> allowedTools)
    {
        AgentInstanceDB agentInstanceDB = new()
        {
            ChatRoomId = chatRoomId,
            TypeId = typeId,
            LLMModel = LLMModel,
            Temperature = temperature,
            AllowedTools = allowedTools,
        };

        return databaseRepository.AddRow(DataBaseTableNames.AgentInstances.ToString(), agentInstanceDB);
    }

    public string GetPresetMessageByAgentTypeId(int agentId)
    {
        AgentTemplateDB agentTemplateDB = new()
        {
            Id = agentId,
        };

        List<AgentTemplateDB> agentTemplateDBs = databaseRepository.QueryRows(DataBaseTableNames.AgentTemplates.ToString(), agentTemplateDB);
        if (agentTemplateDBs.Count == 0)
        {
            return "";
        }
        return agentTemplateDBs[0].PresetMessage;
    }
    
    public AgentTemplateDB? GetAgentTemplateByName(int userId, string agentTemplateName)
    {
        AgentTemplateDB agentTemplateDB = new()
        {
            UserId = userId,
            Name = agentTemplateName,
        };

        List<AgentTemplateDB> agentTemplateDBs = databaseRepository.QueryRows(DataBaseTableNames.AgentTemplates.ToString(), agentTemplateDB);

        if (agentTemplateDBs.Count == 0)
        {
            return null;
        }

        return agentTemplateDBs[0];
    }

    public bool ArchiveChatRoom(int chatRoomId)
    {
        ChatRoomDB chatRoomDB = new()
        {
            Id = chatRoomId,
            Status = ChatRoomDB.ChatRoomStatus.Archived,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);

        if (!success)
        {
            throw new Exception("Archive chat room Id failed.");
        }

        return success;
    }

    public bool DeleteChatRoom(int chatRoomId)
    {
        ChatRoomDB chatRoomDB = new()
        {
            Id = chatRoomId,
            Status = ChatRoomDB.ChatRoomStatus.Delete,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);

        if (!success)
        {
            throw new Exception("Archive chat room Id failed.");
        }

        return success;
    }

    public List<ChatRoomDB> GetChatRoomByProjectId(int projectId)
    {
        ChatRoomDB chatRoomDB = new()
        {
            ProjectId = projectId,
            Status = ChatRoomDB.ChatRoomStatus.Unarchived,
        };

        List<ChatRoomDB> chatRoomDBs = databaseRepository.QueryRows(DataBaseTableNames.ChatRooms.ToString(), chatRoomDB);

        return chatRoomDBs;
    }
    #endregion

    #region Subscriptions
    public void AddOrUpDatePullRequestUserSubscription(bool isActive, int userId, int workflowId, string repositoryURL, bool shouldAskMe)
    {
        UserSubscriptionsDB userSubscriptionsDB = new()
        {
            WorkflowId = workflowId,
        };

        List<UserSubscriptionsDB> userSubscriptionsDBList = databaseRepository.QueryRows(DataBaseTableNames.UserSubscriptions.ToString(), userSubscriptionsDB);

        userSubscriptionsDB = new()
        {
            IsActive = isActive ? 1 : 0,
            UserId = userId,
            WorkflowId = workflowId,
            Address = repositoryURL,
            Class = SubscriptionClass.GitlabPullRequest,
            ShouldAskMe = shouldAskMe ? 1 : 0
        };

        if (userSubscriptionsDBList.Count > 0)
        {
            bool success = databaseRepository.UpdateRowById(DataBaseTableNames.UserSubscriptions.ToString(), userSubscriptionsDB);

            if (success == false)
            {
                throw Debug.ShouldNotHappen();
            }
        }
        else
        {
            databaseRepository.AddRow(DataBaseTableNames.UserSubscriptions.ToString(), userSubscriptionsDB);
        }
    }

    // <subscriptionId, userId>
    public int AddSystematicNotification(Dictionary<string, string> mergeRequestInfo, Tuple<int, int> subscriptionIdAndUserId)
    {
        SystematicNotificationsDB systematicNotificationDB = new()
        {
            SubscriptionId = subscriptionIdAndUserId.Item1,
            UserId = subscriptionIdAndUserId.Item2,
            Content = mergeRequestInfo,
            IsProcessed = 0,
        };

        int notificationId = databaseRepository.AddRow(DataBaseTableNames.SystematicNotifications.ToString(), systematicNotificationDB);
        return notificationId;
    }

    // subscriptionId, userId
    public List<Tuple<int, int>> GetEveryoneWhosubscribes(SubscriptionClass subscriptioClass, string address)
    {
        UserSubscriptionsDB userSubscriptionsDB = new()
        {
            Class = subscriptioClass,
            Address = address,
        };

        List<UserSubscriptionsDB> userSubscriptionsDBList = databaseRepository.QueryRows(DataBaseTableNames.UserSubscriptions.ToString(), userSubscriptionsDB);

        if (userSubscriptionsDBList.Count == 0)
        {
            return [];
        }

        List<Tuple<int, int>> subscriptionIdAndUserId = [];
        foreach (UserSubscriptionsDB userSubscriptionsDBListElement in userSubscriptionsDBList)
        {
            subscriptionIdAndUserId.Add(new Tuple<int, int>(userSubscriptionsDBListElement.Id, userSubscriptionsDBListElement.UserId));
        }

        return subscriptionIdAndUserId;
    }
    
    public List<SystematicNotificationsDB> GetAllSystematicNotificationsByUserId(int userId)
    {
        SystematicNotificationsDB systematicNotificationsDB = new()
        {
            UserId = userId,
        };

        List<SystematicNotificationsDB> notificationsList = databaseRepository.QueryRows(DataBaseTableNames.SystematicNotifications.ToString(), systematicNotificationsDB);

        return notificationsList;
    }
    
    public UserSubscriptionsDB GetUserSubscriptionInfoById(int userSubscriptionId)
    {
        UserSubscriptionsDB userSubscriptionsDB = new()
        {
            Id = userSubscriptionId,
        };

        List<UserSubscriptionsDB> userSubscriptionList = databaseRepository.QueryRows(DataBaseTableNames.UserSubscriptions.ToString(), userSubscriptionsDB);

        if (userSubscriptionList.Count == 0)
        {
            throw Debug.ShouldNotHappen();
        }

        return userSubscriptionList[0];
    }
    #endregion

    #region Workflow
    public string GetWorkflowNameById(int workflowId)
    {
        WorkflowDB workflowDB = new()
        {
            Id= workflowId,
        };

        List<WorkflowDB> workflowDBList = databaseRepository.QueryRows(DataBaseTableNames.WorkflowConfigs.ToString(), workflowDB);
        if(workflowDBList.Count == 0)
        {
            return "";
        }

        return workflowDBList[0].Name;
    }

    public WorkflowDB GetWorkflowById(int workflowId)
    {
        WorkflowDB workflowDB = new()
        {
            Id = workflowId,
        };

        List<WorkflowDB> workflowDBList = databaseRepository.QueryRows(DataBaseTableNames.WorkflowConfigs.ToString(), workflowDB);
        if (workflowDBList.Count == 0)
        {
            throw Debug.ShouldNotHappen();
        }

        return workflowDBList[0];
    }
    #endregion

    #region Manager
    public string GetManagerInvitationCode()
    {
        ManagerUserDB managerUserDB = new();

        List<ManagerUserDB> managerUserDBList = databaseRepository.QueryRows(DataBaseTableNames.ManagerUsers.ToString(), managerUserDB);

        if (managerUserDBList.Count == 0)
        {
            return "";
        }

        return managerUserDBList[0].InvitationCode;
    }

    public List<string> FetchUserAccessibleLlmModels(int userId)
    {
        UserDB userDB = new()
        {
            Id =userId,
        };

        List<UserDB> userDBList = databaseRepository.QueryRows(DataBaseTableNames.Users.ToString(), userDB);
        if (userDBList.Count == 0)
        {
            return [];
        }

        return userDBList[0].AccessChatModels;
    }

    public bool CheckManagerLogin(string username, string password)
    {
        ManagerUserDB managerUserDB = new()
        {
            Name = username,
        };

        List<ManagerUserDB> managerUserDBList = databaseRepository.QueryRows(DataBaseTableNames.ManagerUsers.ToString(), managerUserDB);

        if (managerUserDBList.Count == 0)
        {
            managerUserDBList = databaseRepository.QueryRows(DataBaseTableNames.ManagerUsers.ToString(), new ManagerUserDB());
            if (managerUserDBList.Count > 0)
            {
                return false;
            }

            string invitationCode = InviteManagerModel.GenerateRandomString(6);
            string salt = InviteManagerModel.GenerateRandomString(12);

            managerUserDB = new()
            {
                Name = username,
                Password = HashPassword(password, salt),
                InvitationCode = invitationCode,
                Salt = salt,
            };
            databaseRepository.AddRow(DataBaseTableNames.ManagerUsers.ToString(), managerUserDB);

            return true;
        }

        if (managerUserDBList[0].Password != HashPassword(password, managerUserDBList[0].Salt))
        {
            return false;
        }

        return true;
    }

    public static string HashPassword(string password, string salt)
    {
        byte[] saltBytes = Convert.FromBase64String(salt);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

        using var pbkdf2 = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 10000, HashAlgorithmName.SHA256);
        byte[] hash = pbkdf2.GetBytes(32);
        return Convert.ToBase64String(hash);
    }

    public List<UserDB> GetUserList()
    {
        UserDB userDB = new();

        List<UserDB> userDBList = databaseRepository.QueryRows(DataBaseTableNames.Users.ToString(), userDB);

        return userDBList;
    }

    public void SaveUserPermissions(int userId, List<string> chatPermissions, List<string> workflowPermissions)
    {
        UserDB userDB = new()
        {
            Id = userId,
            AccessChatModels = chatPermissions,
            AccessWorkflowModels = workflowPermissions
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.Users.ToString(), userDB);
        
        if (success == false)
        {
            throw Debug.ShouldNotHappen();
        }
    }

    public bool UpdateInvitationCode(string newInvitationCode)
    {
        ManagerUserDB managerUserDB = new();

        List<ManagerUserDB> managerUserDBList = databaseRepository.QueryRows(DataBaseTableNames.ManagerUsers.ToString(), managerUserDB);

        if (managerUserDBList.Count == 0)
        {
            return false;
        }

        managerUserDB = new ManagerUserDB()
        {
            Id = managerUserDBList[0].Id,
            InvitationCode = newInvitationCode,
        };

        bool success = databaseRepository.UpdateRowById(DataBaseTableNames.ManagerUsers.ToString(), managerUserDB);

        return success;
    }

    public bool DeleteUserById(int userId)
    {
        UserDB userDB = new()
        {
            Id = userId,
        };

        bool success = databaseRepository.DeleteRow(DataBaseTableNames.Users.ToString(), userDB);


        return success;
    }

    public int AddFile(string fileName, string fileContent)
    {
        FilesDB filesDB = new()
        {
            FileName = fileName,
            Content = fileContent,
        };

        int fileId = databaseRepository.AddRow(DataBaseTableNames.Files.ToString(), filesDB);

        return fileId;
    }

    public FilesDB? GetFileById(int fileId)
    {
        FilesDB filesDB = new()
        {
            Id = fileId,
        };

        List<FilesDB> filesDBList = databaseRepository.QueryRows(DataBaseTableNames.Files.ToString(), filesDB);
        if (filesDBList.Count == 0)
        {
            return null;
        }

        return filesDBList[0];
    }
    #endregion

    #region File
    public FilesDB? GetFileContent(int fileId)
    {
        FilesDB filesDB = new()
        {
            Id = fileId,
        };

        List<FilesDB> filesDBList = databaseRepository.QueryRows(DataBaseTableNames.Files.ToString(), filesDB);

        if (filesDBList.Count == 0)
        {
            return null;
        }

        return filesDBList[0];
    }
    #endregion
}
